package client.xmpp;

import java.util.Collection;
//import java.util.HashMap;

import org.jivesoftware.smackx.packet.Version;
import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ChatManager;
//import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
//import org.jivesoftware.smack.RosterListener;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketIDFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Presence.Type;

public class XmppManager {
	
	private static final int packetReplyTimeout = 5000; // ms
	
	private String server;
	private int port;
	
	private ConnectionConfiguration config;
	private XMPPConnection connection;
	
	private ChatManager chatManager;
	private MessageListener messageListener;
	private boolean debugEnabled = false;

/** Constructor
 * 	
 * @param server
 * @param port
 * @param debug
 */
	public XmppManager(String server, int port, boolean debugEnabled ) {
		this.server = server;
		this.port = port;
		this.debugEnabled = debugEnabled;
	}
	
	public void init() throws XMPPException {
		
		System.out.println(String.format("Initializing connection to server %1$s port %2$d", server, port));

		SmackConfiguration.setPacketReplyTimeout(packetReplyTimeout);
//		System.out.println("Keepalive: " + SmackConfiguration.getKeepAliveInterval() +" ms.");
		config = new ConnectionConfiguration(server, port);
 
		XMPPConnection.DEBUG_ENABLED = debugEnabled;
		if (debugEnabled) { 
			connection = new XMPPConnection(server);
		} else {
			connection = new XMPPConnection(config);	
		}
		connection.connect();
		
//		ConnectionListener 

		System.out.println("Connected to " + connection.getHost() + " on port "+connection.getPort());
		
		chatManager = connection.getChatManager();
		messageListener = new MyMessageListener();
		
	}
	
	public void printServerVersion() {
		// Request the version from the server.
		Version versionRequest = new Version();
		versionRequest.setType(IQ.Type.GET);
		versionRequest.setTo(server);
		versionRequest.setFrom(connection.getUser());

		// Create a packet collector to listen for a response.
		PacketCollector collector = connection.createPacketCollector(
		                new PacketIDFilter(versionRequest.getPacketID()));

		connection.sendPacket(versionRequest);

		// Wait up to 5 seconds for a result.
		IQ result = (IQ)collector.nextResult(5000);
		if (result != null && result.getType() == IQ.Type.RESULT) {
		     Version versionResult = (Version)result;
		     System.out.println("Version: "+versionResult.getVersion());
		}

	}
	public void performLogin(String username, String password) throws XMPPException {
		if (connection!=null && connection.isConnected()) {
			connection.login(username, password);
			System.out.println("Logged in as: " + connection.getUser());
		}
	}
	public Roster getRoster() throws XMPPException {
			Roster roster = connection.getRoster();
			return roster; 
	}

	public void setStatus(boolean available, String status) {
		
		Presence.Type type = available? Type.available: Type.unavailable;
		Presence presence = new Presence(type);
		
		presence.setStatus(status);
		connection.sendPacket(presence);
		
	}
	
	public void destroy() {
		if (connection!=null && connection.isConnected()) {
			connection.disconnect();
		}
	}
	
	public String[][] returnRoster() throws Exception {
		Presence presence;
		String name="", userid;
		Roster roster = connection.getRoster();
		Collection<RosterEntry> entries = roster.getEntries();
		String[][] array = new String[ roster.getEntryCount() ][] ;
		int i=0;
		for (RosterEntry entry : entries) {
			presence = roster.getPresence(entry.getUser());
			name = entry.getName();
			userid = entry.getUser();
			if (name==null) name="";
			String row[]={ userid, name, presence.toString() };
			array[i++]=row;
			System.out.println(String.format("%1$s<%2$s> %3$s", 
					name, userid, presence.toString()));
		}
		return array;
	}
	
	public void sendMessage(String message, String buddyJID) throws XMPPException {
		System.out.println(String.format("Sending mesage '%1$s' to user %2$s", message, buddyJID));
		Chat chat = chatManager.createChat(buddyJID, messageListener);
		chat.sendMessage(message);
	}
	
	public void createEntry(String user, String name) throws Exception {
		System.out.println(String.format("Creating entry for buddy '%1$s' with name %2$s", user, name));
		Roster roster = connection.getRoster();
		roster.createEntry(user, name, null);
	}
	
	class MyMessageListener implements MessageListener {

		@Override
		public void processMessage(Chat chat, Message message) {
			String from = message.getFrom();
			String body = message.getBody();
			System.out.println(String.format("Received message '%1$s' from %2$s", body, from));
		}
	}
	
	public void pingServer() throws XMPPException {

		PingIQ pingServer = new PingIQ();	// <Ping IQ stanza
		pingServer.setType(IQ.Type.GET);
		pingServer.setTo(server);
		pingServer.setFrom(connection.getUser());

		PacketCollector collector = connection.createPacketCollector(
			new PacketIDFilter(pingServer.getPacketID()));

		System.out.println("Sending ping: "+pingServer.getPacketID());
		
		long sendTime = System.currentTimeMillis();
		connection.sendPacket(pingServer);
		
		IQ result = (IQ)collector.nextResult(5000);
		if (result != null && result.getType() == IQ.Type.RESULT) {
			System.out.println("Received pong: "+result.getPacketID()+ 
					" after " + (System.currentTimeMillis()-sendTime) + " milliseconds.");
		}
	}
}
